package cn.qingyun.gis.modules.express.service.impl;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.qingyun.gis.modules.express.entity.Point;
import cn.qingyun.gis.modules.express.service.IGdRestApiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Objects;

@Service
@Slf4j
public class GdRestApiServiceImpl implements IGdRestApiService {

    @Value("${qingyun.gd.service-host:http://127.0.0.1}")
    private String gdServiceHost;

    @Override
    @Cacheable(value = "caches", key = "#address")
    public Point geoGetXy(String address, String city) {
        try {
            String requestUrl = String.format("%s/geo/get/xy?address=%s",
                    gdServiceHost, address);
            log.debug("地址转坐标:{}", requestUrl);

            HttpResponse httpResponse = HttpUtil.createGet(requestUrl).timeout(1000).execute();

            if (httpResponse.isOk()) {
                JSONObject parseObj = JSONUtil.parseObj(httpResponse.body());
                String location = (String) parseObj.getByPath("data.list[0].location");
                String[] split = location.split(",");

                return new Point(NumberUtil.toBigDecimal(split[0]), NumberUtil.toBigDecimal(split[1]));
            }
        } catch (Exception e) {
            log.error("地址转换失败", e);
        }
        return null;
    }

    @Override
    public String getWkt(Integer source, Integer cityId, Integer communityId, String location) {
        try {
            String requestUrl = String.format("%s/merge/address/query/around?source=%s&level=poi&poiCode=%s&cityCode=%s&location=%s&radius=3000",
                    gdServiceHost, source, cityId, communityId, location);
            log.debug("获取小区边界:{}", requestUrl);

            HttpResponse httpResponse = HttpUtil.createGet(requestUrl).timeout(1000).execute();

            if (httpResponse.isOk()) {
                JSONObject parseObj = JSONUtil.parseObj(httpResponse.body());
                Object byPath = parseObj.getByPath("data[0].wkt");

                if (Objects.nonNull(byPath)) {
                    return (String) byPath;
                }
            }
        } catch (Exception e) {
            log.error("获取获取小区边界失败", e);
        }
        return null;
    }

    @Override
    public Double getDistance(String fromLocation, String toLocation) {
        String requestUrl = null;
        try {
            String[] fromSplit = fromLocation.split(",");
            String[] toSplit = toLocation.split(",");

            requestUrl = String.format("%s/datahub/api/gis/dis/pointToPoint?startLon=%s&startLat=%s&endLon=%s&endLat=%s",
                    gdServiceHost, fromSplit[0], fromSplit[1], toSplit[0], toSplit[1]);

            HttpResponse httpResponse = HttpUtil.createGet(requestUrl).timeout(1000).execute();

            if (httpResponse.isOk()) {
                JSONObject parseObj = JSONUtil.parseObj(httpResponse.body());
                return parseObj.getDouble("data");
            }
        } catch (Exception e) {
            log.error("获取获取小区边界失败 {}", requestUrl, e);
        }
        return 0D;
    }

    @Override
    public String getPoiName(String poiId) {
        String requestUrl = null;
        try {
            requestUrl = String.format("%s/query/placedetail?id=%s",
                    gdServiceHost, poiId);

            HttpResponse httpResponse = HttpUtil.createGet(requestUrl).timeout(1000).execute();

            if (httpResponse.isOk()) {
                JSONObject parseObj = JSONUtil.parseObj(httpResponse.body());
                Object byPath = parseObj.getByPath("pois[0].name");
                if (Objects.nonNull(byPath)) {
                    return String.valueOf(byPath);
                }
            }
        } catch (Exception e) {
            log.error("获取Poi名称失败 {}", requestUrl, e);
        }
        return null;
    }

    @Override
    public Point convertLocation(BigDecimal lon, BigDecimal lat, String coordsys) {
        String requestUrl = null;
        try {
            requestUrl = String.format("%s/v3/assistant/coordinate/convert?coordsys=%s&locations=%s,%s",
                    gdServiceHost, coordsys, lon, lat);
            HttpResponse httpResponse = HttpUtil.createGet(requestUrl).timeout(1000).execute();
            if (httpResponse.isOk()) {
                JSONObject parseObj = JSONUtil.parseObj(httpResponse.body());
                String locations = parseObj.getStr("locations");
                if (StrUtil.isNotBlank(locations)) {
                    String[] split = locations.split(",");
                    if (split.length == 2) {
                        return new Point(NumberUtil.toBigDecimal(split[0]).setScale(6, RoundingMode.UP),
                                NumberUtil.toBigDecimal(split[1]).setScale(6, RoundingMode.UP));
                    }
                }
            }
        } catch (Exception e) {
            log.error("地址转换失败 {}", requestUrl, e);
        }
        return null;
    }

    @Override
    public JSONObject getPoiBy(Integer cityCode, Integer communityId, String keyword) {
        String requestUrl = null;
        try {
            requestUrl = String.format("%s/merge/address/query/keyword?keyword=%s&source=1&level=poi&cityCode=%s&poiCode=%s",
                    gdServiceHost, keyword, cityCode, communityId);

            HttpResponse httpResponse = HttpUtil.createGet(requestUrl).timeout(1000).execute();

            if (httpResponse.isOk()) {
                JSONObject parseObj = JSONUtil.parseObj(httpResponse.body());
                return parseObj.getByPath("data[0]", JSONObject.class);
            }
        } catch (Exception e) {
            log.error("获取Poi详情失败 {}", requestUrl, e);
        }
        return null;
    }

    @Override
    public Integer pointToPolygon(Double lon, Double lat, String polygon) {
        String requestUrl = null;
        try {
            requestUrl = String.format("%s/datahub/api/gis/topo/pointToPolygon?lat=%s&lon=%s&polygon=%s",
                    gdServiceHost, lat, lon, polygon);

            HttpResponse httpResponse = HttpUtil.createGet(requestUrl).timeout(1000).execute();

            if (httpResponse.isOk()) {
                JSONObject parseObj = JSONUtil.parseObj(httpResponse.body());
                log.debug(String.format("点面关系返回结果：%s", parseObj.getInt("data")));
                return parseObj.getInt("data");
            }
        } catch (Exception e) {
            log.error("点面关系判断失败 {}", requestUrl, e);
        }
        return null;
    }
}
